
#include "my_serial.h"
#include "PubSubClient.h"
#include <Arduino.h>
#include <Ticker.h>
#include <ESP8266WiFi.h>
#include <SPI.h>
#include <Wire.h>
#include <U8g2lib.h>
// define
#define DEBUG 0
#define KI_LG 14
#define KO_FIRE 12
#define KO_PWR 13
#if DEBUG
#define AUTO_TIME 1000  // 80s
#define PWR_TIME 250    // 20s
#define FIRE_TIME 125   // 10s
#define SHOW_TIME 100   // 8s
#else
#define AUTO_TIME 45000  // 1hour
#define PWR_TIME 1250    // 100s
#define FIRE_TIME 125    // 10s
#define SHOW_TIME 100    // 8s
#endif


// Objets
MY_Serial my_serial;
Ticker ticker_80ms;
// u8g2
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE, D1, D2);
char str_buff_dd[32] = { 0 };
char str_buff_rw[32] = { 0 };
// WIFI
const char *ssid = "Redmi K60";
const char *password = "miaojusky";
// bemfa cloud mqtt
const char *mqtt_server = "bemfa.com";
const int mqtt_server_port = 9501;
#define ID_MQTT "713b27cb2c0f4c579f468a809e9787e4"
const char *topic = "Test002";
WiFiClient espClient;
PubSubClient client(espClient);
// Global
char SendUartFlag = 0;
char SendMqttFlag = 0;
char WiFi_Fail_Cnt = 0;
String mqttstatus = "正在联网";
String teststatus = "正在测试";

long int task_timer = PWR_TIME+250;  // Seconds*12.5 ------80ms-1

void tick80ms(void) {

#if DEBUG
  // Serial.println("one second tick!");
#endif
  // dispaly
  sprintf(str_buff_dd, "弹计通讯计数：%03d", my_serial.cnt);
  sprintf(str_buff_rw, "点火倒数计时：%04d秒", task_timer/10);
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_wqy12_t_gb2312);
  u8g2.drawUTF8(0, 15, str_buff_dd);
  u8g2.drawUTF8(0, 30, str_buff_rw);
  u8g2.drawUTF8(0, 45, teststatus.c_str());
  u8g2.drawUTF8(0, 60, mqttstatus.c_str());
  u8g2.sendBuffer();
  if (task_timer == PWR_TIME) {
    if (digitalRead(KI_LG)) {
      teststatus = "上电前离轨错误";
      SendMqttFlag = 1;
      task_timer = SHOW_TIME;
    } else {
    }
  }
  if (task_timer < PWR_TIME) {
    turnOnPwr();
    // send Uart
    SendUartFlag = 1;
    //check LG
    if (task_timer > FIRE_TIME) {
      if (digitalRead(KI_LG)) {
        teststatus = "上电后离轨错误";
        SendMqttFlag = 1;
        task_timer = SHOW_TIME;
      } else {
      }
    }
    if(task_timer > SHOW_TIME)
    {//check TX
      if (my_serial.check & 0x40) {
        teststatus = "弹计上报通讯错误";
        SendMqttFlag = 1;
        task_timer = SHOW_TIME;
      } else {
      }
      //check RX
      my_serial.timcheck++;
      if (my_serial.timcheck >4) {
        teststatus = "弹计数据接收错误";
        SendMqttFlag = 1;
        task_timer = SHOW_TIME;
      } else {
      }}
    else{
    }
  } 
  else {
    turnOffPwr();
  }
  if ((task_timer == (FIRE_TIME + 1)) || (task_timer == FIRE_TIME)) {
    turnOnFire();
  } else {
    turnOffFire();
  }
  if (task_timer == (FIRE_TIME - 10)) {
    if (digitalRead(KI_LG)) {
      teststatus = "测试成功!";
      SendMqttFlag = 1;
      task_timer = SHOW_TIME;
    } else {
      teststatus = "点火不离轨错误";
      SendMqttFlag = 1;
      task_timer = SHOW_TIME;
    }
  }
  if (task_timer > 0) {
    task_timer--;
  } else {
    task_timer = AUTO_TIME;
  }
}
// pwr control
void turnOnPwr() {

#if DEBUG
  Serial.println("turn on pwr");
#endif
  digitalWrite(KO_PWR, HIGH);
}
void turnOffPwr() {

#if DEBUG
  Serial.println("turn off pwr");
#endif
  digitalWrite(KO_PWR, LOW);
}
// fire control
void turnOnFire() {

#if DEBUG
  Serial.println("turn on fire");
#endif
  digitalWrite(KO_FIRE, HIGH);
}
void turnOffFire() {

#if DEBUG
  Serial.println("turn off fire");
#endif
  digitalWrite(KO_FIRE, LOW);
}
// mqtt
void callback(char *topic, byte *payload, unsigned int length) {
#if DEBUG
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
#endif
  String Mqtt_Buff = "";
  for (int i = 0; i < length; i++) {
    Mqtt_Buff += (char)payload[i];
  }
#if DEBUG
  Serial.print(Mqtt_Buff);
  Serial.println();
#endif
  if (Mqtt_Buff == "on") {

    task_timer = PWR_TIME;
  } else if (Mqtt_Buff == "off") {
    task_timer = 0;
  }

  Mqtt_Buff = "";
}
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
#if DEBUG
    Serial.print("Attempting MQTT connection...");
#endif
    // Attempt to connect
    if (client.connect(ID_MQTT)) {
#if DEBUG
      Serial.println("connected");
#endif
      client.subscribe(topic);
    } else {
#if DEBUG
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
#endif
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
void setup() {
  // initialize PINs:
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);  // on-Low off-High
  pinMode(KO_FIRE, OUTPUT);
  digitalWrite(KO_FIRE, LOW);  // on-HIGH off-LOW
  pinMode(KO_PWR, OUTPUT);
  digitalWrite(KO_PWR, LOW);  // on-HIGH off-LOW
  pinMode(KI_LG, INPUT);

  my_serial.setup();
  u8g2.begin();
  ticker_80ms.attach_ms(80, tick80ms);
#if DEBUG
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
#endif
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
#if DEBUG
    Serial.print(".");
#endif
    WiFi_Fail_Cnt++;
    if (WiFi_Fail_Cnt % 2) {
      digitalWrite(LED_BUILTIN, LOW);
    } else {
      digitalWrite(LED_BUILTIN, HIGH);
    }
    if (WiFi_Fail_Cnt > 12) {
#if DEBUG
      Serial.println("connect wifi failed!");
#endif
      mqttstatus = "没有网络热点";
      WiFi.disconnect();
      break;
    }
  }
  if (WiFi.status() == WL_CONNECTED) {
    digitalWrite(LED_BUILTIN, HIGH);
#if DEBUG
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
#endif
    client.setServer(mqtt_server, mqtt_server_port);
    client.setCallback(callback);
#if DEBUG
    Serial.println("mqtt started");
#endif
  }
}  
void loop() {
#if DEBUG
  Serial.println("loop");
#endif
  my_serial.rev_uart();
  if (SendUartFlag) {
    SendUartFlag = 0;
    my_serial.send_uart();
  }
  if (WiFi_Fail_Cnt <= 12) {
    if (!client.connected()) {
      reconnect();
      mqttstatus = "找不到服务器";
    } else {
      mqttstatus = "已连接服务器";
      if (SendMqttFlag) {
        SendMqttFlag = 0;
        client.publish(topic, teststatus.c_str());
      }
    }
    client.loop();
  }
}
